package com.ouroboroswiki.core.content.fallback;

import java.util.ArrayList;
import java.util.Map;

import com.ouroboroswiki.core.AbstractContentRepository;
import com.ouroboroswiki.core.Content;
import com.ouroboroswiki.core.ContentException;
import com.ouroboroswiki.core.ContentPath;
import com.ouroboroswiki.core.ContentRepository;
import com.ouroboroswiki.core.ContentUtil;
import com.ouroboroswiki.core.Version;
import com.ouroboroswiki.core.VersionBuilder;

public class FallbackContentRepositoryProxy extends AbstractContentRepository {
	
	private ContentRepository proxied;
	
	public FallbackContentRepositoryProxy( ContentRepository proxied ) {
		this.proxied = proxied;
	}
	
	public ContentPath fallback(Object principal, ContentPath path) 
		throws ContentException {
		ArrayList<ContentPath> splits = ContentUtil.split(path);
		// walk all the paths
		for( int i=splits.size(); i>0; ) {
			i--;
			ContentPath split = splits.get(i);
			ArrayList<ContentPath> paths = new ArrayList<ContentPath>();
			ContentPath p = split;
			String lastPathName = null;
			while( true ) {
				paths.add(p);
				ContentPath onlyChild = p.getOnlyChild();
				if( onlyChild != null ) {
					p = onlyChild;
				} else {
					lastPathName = p.getName();
					break;
				}
			}
			boolean done = false;
			ContentPath myPath = split;
			while( !done ) {
				if( proxied.exists(principal, myPath) ) {
					done = true;
				} else {
					
					if( lastPathName.length() > 0 ) {
						int index = lastPathName.lastIndexOf('/');
						if( index >= 0 ) {
							lastPathName = lastPathName.substring(0, index);
							// assumes this isn't cached anywhere
						} else {
							lastPathName = "";
						}
						ContentPath newPath = new ContentPath( 
								lastPathName
						);
						for( int j=paths.size()-1; j>0; ) {
							j--;
							ContentPath o = paths.get( j );
							newPath = new ContentPath( o.getName(), newPath, o.isContextualBreak() );
						}
						myPath = newPath;
					} else {
						// revert to original
						myPath = split;
						break;
					}
				}
			}
			splits.set(i, myPath);
		}
		return ContentUtil.mergeToPath(splits);
	}

	@Override
	public boolean exists(Object principal, ContentPath path) throws ContentException {
		ContentPath p = fallback(principal, path);
		boolean result = proxied.exists(principal, p);
		return result;
	}
	
	@Override
	public Content getContent(Object principal, ContentPath path, Version version, Map<String, Object> properties)
			throws ContentException {
		ContentPath p = fallback(principal, path);
		Content result = proxied.getContent(principal, p, version, properties);
		return result;
	}

	@Override
	public Version buildVersion(Object principal, ContentPath path,
			String[] versionPath, VersionBuilder versionBuilder) throws ContentException {
		ContentPath p = fallback(principal, path);
		Version result = proxied.buildVersion(principal, p, versionPath, versionBuilder);
		return result;
	}

}
